package raft

//
// this is an outline of the API that raft must expose to
// the service (or tester). see comments below for
// each of these functions for more details.
// 这是Raft必须向(外部的)服务(或测试人员)提供的API概要
// 下面将叙述这些函数的更多细节
//
// rf = Make(...)
//   create a new Raft server.
// 创建一个新的Raft服务器
// rf.Start(command interface{}) (index, term, isleader)
//   start agreement on a new log entry
// 开始新日志条目的协议
// rf.GetState() (term, isLeader)
//   ask a Raft for its current term, and whether it thinks it is leader
// 询问Raft的当前任期，以及它是否认为自己是领导者
// ApplyMsg 这是一个传递消息的变量
//   each time a new entry is committed to the log, each Raft peer
//   should send an ApplyMsg to the service (or tester)
//   in the same server.
// 每次向日志提交新条目时，
// 每个Raft对等节点都应该向同一服务器中的服务（或测试人员）发送ApplyMsg
//

import (
	"sync"
	"sync/atomic"

	"raft/labrpc"
)

// import "bytes"
// import "../labgob"

// as each Raft peer becomes aware that successive log entries are
// committed, the peer should send an ApplyMsg to the service (or
// tester) on the same server, via the applyCh passed to Make(). set
// CommandValid to true to indicate that the ApplyMsg contains a newly
// committed log entry.
// 当每个Raft peer意识到连续的log entries已经被提交后
// 该peer应当给同一服务器上的服务(或测试者)发送一个ApplyMsg信息
// 该请求通过由Make()函数传递的applyCh对象实现.
// 在实现中,applyCh是一个Golang管道
//
// in Lab 3 you'll want to send other kinds of messages (e.g.,
// snapshots) on the applyCh; at that point you can add fields to
// ApplyMsg, but set CommandValid to false for these other uses.
// 在Lab3中你将在applyCh管道中发送其它类型的信息(例如snapshots)
// 在那时你就可以向ApplyMsg类添加其它变量,
// 但同时你需要设置CommandValid=false时才能使用
// 通过这种方式可以区分Command变量存储的是指令还是其它数据
type ApplyMsg struct {
	CommandValid bool
	Command      interface{}
	CommandIndex int
}

// A Go object implementing a single Raft peer.
type Raft struct {
	mu        sync.Mutex          // Lock to protect shared access to this peer's state
	peers     []*labrpc.ClientEnd // RPC end points of all peers
	persister *Persister          // Object to hold this peer's persisted state
	me        int                 // this peer's index into peers[]
	dead      int32               // 由Kill()函数设置

	// Your data here (2A, 2B, 2C).
	// 2A,2B,2C的所有数据类型均在下方定义
	// Look at the paper's Figure 2 for a description of what
	// state a Raft server must maintain.
	// 根据论文的Figure 2添加描述一个Raft服务器所必须的包含的状态变量
}

// return (当前的任期编号,服务器是否认为它是leader)
// return (currentTerm,isleader)
func (rf *Raft) GetState() (int, bool) {

	var term int
	var isleader bool
	// Your code here (2A).
	return term, isleader
}

// save Raft's persistent state to stable storage,
// where it can later be retrieved after a crash and restart.
// see paper's Figure 2 for a description of what should be persistent.
// 存储Raft的持久化状态到持久性存储中
// 这样节点之后就可以在崩毁重启后恢复
// 论文Figure 2中描述了哪些需要持久化存储
func (rf *Raft) persist() {
	// Your code here (2C).
	// Example:
	// w := new(bytes.Buffer)
	// e := labgob.NewEncoder(w)
	// e.Encode(rf.xxx)
	// e.Encode(rf.yyy)
	// data := w.Bytes()
	// rf.persister.SaveRaftState(data)
}

// restore previously persisted state.
// 重载之前的持久化状态
func (rf *Raft) readPersist(data []byte) {
	if data == nil || len(data) < 1 { // bootstrap without any state?
		return
	}
	// Your code here (2C).
	// Example:
	// r := bytes.NewBuffer(data)
	// d := labgob.NewDecoder(r)
	// var xxx
	// var yyy
	// if d.Decode(&xxx) != nil ||
	//    d.Decode(&yyy) != nil {
	//   error...
	// } else {
	//   rf.xxx = xxx
	//   rf.yyy = yyy
	// }
}

// example RequestVote RPC arguments structure.
// field names must start with capital letters!
// [样例]RequestVote RPC函数的参数的数据结构
// 其变量名称必须使用大写字母开头
type RequestVoteArgs struct {
	// Your data here (2A, 2B).
}

// example RequestVote RPC reply structure.
// field names must start with capital letters!
// [样例]RequestVote RPC回复数据的数据结构
// 其变量名称必须使用大写字母开头
type RequestVoteReply struct {
	// Your data here (2A).
}

// example RequestVote RPC handler.
// [样例]RequestVote RPC函数
func (rf *Raft) RequestVote(args *RequestVoteArgs, reply *RequestVoteReply) {
	// Your code here (2A, 2B).
}

// example code to send a RequestVote RPC to a server.
// 对一个服务器发起RequestVote RPC请求的样例代码
// server is the index of the target server in rf.peers[].
// server变量(int)是在rf.peers[]中的目标服务器的下标
// expects RPC arguments in args.
// fills in *reply with RPC reply, so caller should
// pass &reply.
// the types of the args and reply passed to Call() must be
// the same as the types of the arguments declared in the
// handler function (including whether they are pointers).
// 传递给Call()函数的args和reply参数的类型
// 必须同在handler函数中声明的类型是相同的
// (这也包括是否他们是指针)
//
// The labrpc package simulates a lossy network, in which servers
// may be unreachable, and in which requests and replies may be lost.
// labrpc包模拟了一个有损网络,其中服务器可能访问不可达
// 并且请求和回复都有可能会丢失
// Call() sends a request and waits for a reply. If a reply arrives
// within a timeout interval, Call() returns true; otherwise
// Call() returns false. Thus Call() may not return for a while.
// Call()发送了一个请求并等待回复
// 如果回复在timeout时间内到达,Call()返回true,否则返回false
// 因此Call()可能在一段时间内不会返回
// A false return can be caused by a dead server, a live server that
// can't be reached, a lost request, or a lost reply.
// 一个false的返回值可能来源于一个宕机的服务器,一个存活但网络不可达的服务器
// 一个丢失的请求或者一定丢失的回复
//
// Call() is guaranteed to return (perhaps after a delay) *except* if the
// handler function on the server side does not return.  Thus there
// is no need to implement your own timeouts around Call().
// Call()函数会确保(也许在一定延迟后)返回,除非你定义在服务器端的函数handler
// 没有返回. 因此,你没有必要在Call()的前后实现自己的timeouts.
//
// look at the comments in ../labrpc/labrpc.go for more details.
// 更多细节请查阅../labrpc/labrpc.go中的注释
//
// if you're having trouble getting RPC to work, check that you've
// capitalized all field names in structs passed over RPC, and
// that the caller passes the address of the reply struct with &, not
// the struct itself.
// 如果你已经无法使RPC正常工作,
// 请检查是否已将通过RPC传递的结构中的所有字段名大写
// 并且调用方是否使用'&'来获取reply变量的地址,而不是reply变量本身。
// 指定参数类型是指针,系统会自动从指针指向的对象中获取数据并传输
func (rf *Raft) sendRequestVote(server int, args *RequestVoteArgs, reply *RequestVoteReply) bool {
	ok := rf.peers[server].Call("Raft.RequestVote", args, reply)
	return ok
}

// the service using Raft (e.g. a k/v server) wants to start
// agreement on the next command to be appended to Raft's log. if this
// server isn't the leader, returns false. otherwise start the
// agreement and return immediately. there is no guarantee that this
// command will ever be committed to the Raft log, since the leader
// may fail or lose an election. even if the Raft instance has been killed,
// this function should return gracefully.
// 使用Raft的服务(例如一个k/v服务器)想要在下一个command指令被追加到raft-log
// 就必须在追加操作执行前所有服务器达成共识.
// 如果这个服务器不是leader,就返回false. 否则就达成共识并立即返回
// 由于leader可能会出错或在选举中失败,因此无法保证该command将永远提交给raft-log
// 即便raft实例被系统kill掉,这个函数也应当平滑地退出
//
// the first return value is the index that the command will appear at
// if it's ever committed. the second return value is the current
// term. the third return value is true if this server believes it is
// the leader.
// 第一个返回值是command在已经提交时出现的索引
// 第二个返回值是当前任期
// 如果该服务器认为它是leader,则第三个返回值为true。
func (rf *Raft) Start(command interface{}) (int, int, bool) {
	index := -1
	term := -1
	isLeader := true

	// Your code here (2B).

	return index, term, isLeader
}

// the tester doesn't halt goroutines created by Raft after each test,
// but it does call the Kill() method. your code can use killed() to
// check whether Kill() has been called. the use of atomic avoids the
// need for a lock.
// 测试程序不会在每次测试后停止Raft创建的goroutine,但会调用Kill()方法
// 您的代码可以使用killed()检查是否已调用Kill()函数
// sync/atomic包的使用避免了在此处再额外添加一个锁
//
// the issue is that long-running goroutines use memory and may chew
// up CPU time, perhaps causing later tests to fail and generating
// confusing debug output. any goroutine with a long-running loop
// should call killed() to check whether it should stop.
// 问题是,长时间运行的goroutine使用内存,可能会占用CPU时间,
// 这可能会导致后续测试失败,并产生令人困惑的调试输出
// 任何具有长时间循环的goroutine都应该调用killed()来检查它是否应该停止
func (rf *Raft) Kill() {
	atomic.StoreInt32(&rf.dead, 1)
	// Your code here, if desired.
	// 实现平滑地系统退出机制
}

func (rf *Raft) killed() bool {
	z := atomic.LoadInt32(&rf.dead)
	return z == 1
}

// the service or tester wants to create a Raft server. the ports
// of all the Raft servers (including this one) are in peers[]. this
// server's port is peers[me]. all the servers' peers[] arrays
// have the same order. persister is a place for this server to
// save its persistent state, and also initially holds the most
// recent saved state, if any. applyCh is a channel on which the
// tester or service expects Raft to send ApplyMsg messages.
// Make() must return quickly, so it should start goroutines
// for any long-running work.
// 服务或测试人员想要创建Raft服务器
// 所有Raft服务器(包括此服务器)的端口都保存在peers[]中
// 本服务器自身的port信息存储在peers[me]中
// 所有服务器的peers[]数据具有相同的排序
// persister是该服务器保存其持久状态的地方,并且最初保存着最近状态信息(如果有的话)
// applyCh是测试人员或服务希望Raft在其上发送ApplyMsg消息的channel
// Make()函数必须快速返回,因此它应该为任何长时间运行的工作启动goroutine
//
// 简单来说:
// func Make(
//
//	peers[]   集群内的所有服务器的端口列表
//	me        列表peers[me]表示服务器自己的端口
//	persister 指向持久存储数据的对象的指针
//	applyCh   提供给本raft节点发送消息的go-channel
//
// )
func Make(peers []*labrpc.ClientEnd, me int,
	persister *Persister, applyCh chan ApplyMsg) *Raft {
	rf := &Raft{}
	rf.peers = peers
	rf.persister = persister
	rf.me = me

	// Your initialization code here (2A, 2B, 2C).

	// initialize from state persisted before a crash
	// 读取持久化状态数据,从崩溃前保持的状态初始化
	rf.readPersist(persister.ReadRaftState())

	return rf
}
